﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Eqwww.Data;
using Eqwww.Domain.Models.SystemManage;
using Eqwww.Domain;
using Eqwww.Code;

namespace Eqwww.App.SystemManage
{
    public class ModuleButtonApp
    {
        private ApplicationDbContext _context;
        private DatabaseLogApp _dbLogApp;
        private IModelHandler _modelHandler;

        public ModuleButtonApp(ApplicationDbContext context,
            DatabaseLogApp databaseLogApp,
            IModelHandler modelHandler)
        {
            _context = context;
            _dbLogApp = databaseLogApp;
            _modelHandler = modelHandler;
        }

        /// <summary>
        /// 新建模块
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ModelResult Create(ModuleButtonModel model)
        {
            if (IsExistCode(model.Code))
            {
                return Common.ErrorResult("编码不能重复");
            }
            if (string.IsNullOrEmpty(model.ParentId))
                model.Layer = 0;
            else
            {
                var parent = _context.Sys_ModuleButtons.FirstOrDefault(x => x.Id == model.ParentId);
                if (parent == null)
                {
                    return Common.ErrorResult("未找到指定的上级按钮");
                }
                model.Layer = parent.Layer + 1;
            }

            _modelHandler.Create(model);
            _context.Sys_ModuleButtons.Add(model);
            _dbLogApp.LogCreateInformation(model.Id, model, "创建按钮");
            _context.SaveChanges();

            return Common.SuccessResult();
        }

        public ModelResult CreateRange(ModuleButtonModel[] models)
        {
            foreach (var model in models)
            {
                if (IsExistCode(model.Code))
                {
                    return Common.ErrorResult("编码不能重复");
                }
                if (string.IsNullOrEmpty(model.ParentId))
                    model.Layer = 0;
                else
                {
                    var parent = _context.Sys_ModuleButtons.FirstOrDefault(x => x.Id == model.ParentId);
                    if (parent == null)
                    {
                        return Common.ErrorResult("未找到指定的上级按钮");
                    }
                    model.Layer = parent.Layer + 1;
                }

                _modelHandler.Create(model);
                _context.Sys_ModuleButtons.Add(model);
                _dbLogApp.LogCreateInformation(model.Id, model,"创建按钮【批量】");
            }

            _context.SaveChanges();
            return Common.SuccessResult();
        }

        /// <summary>
        /// 获取所有模块和按钮的树形菜单开关列表
        /// </summary>
        /// <returns></returns>
        public List<TreeCollapseToggleModel> GetModuleAndButtonTreeCollapseToggleList()
        {
            var data = new List<TreeCollapseToggleModel>();

            var modules = from p in _context.Sys_Modules.AsNoTracking().Where(x => x.DeleteMark != true)
                          select new TreeCollapseToggleModel
                          {
                              Id = p.Id,
                              Text = p.Name,
                              Url = p.Url,
                              ParentId = p.ParentId,
                              SortCode = p.SortCode,
                              Icon = "list",
                              CanToggle = false,
                              Expend=true
                          };

            var buttons = from p in _context.Sys_ModuleButtons.AsNoTracking().Where(x => x.DeleteMark != true)
                          select new TreeCollapseToggleModel
                          {
                              Id = p.Id,
                              Text = p.Name,
                              Url = p.Url,
                              ParentId = string.IsNullOrEmpty(p.ParentId) ? p.ModuleId : p.ParentId,
                              SortCode = p.SortCode,
                              Icon = "touch_app",
                              CanToggle=true,
                              Expend=true
                          };
            data.AddRange(modules);
            data.AddRange(buttons);
            return data;
        }

        public ModelResult CloneButtons(string moduleId, string parentId, string[] buttonIds)
        {
            var buttons = _context.Set<ModuleButtonModel>().Where(x => buttonIds.Contains(x.Id)).AsNoTracking().ToList();
            foreach(var item in buttons)
            {
                _modelHandler.Create(item);
                item.Code += Guid.NewGuid().ToString();
                item.ModuleId = moduleId;
                item.ParentId = parentId;
                _context.Add(item);
            }
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        /// <summary>
        /// 更新模块
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ModelResult Update(ModuleButtonModel model)
        {
            var oldModel = _context.Sys_ModuleButtons.AsNoTracking().FirstOrDefault(x => x.Id == model.Id);
            if (oldModel == null)
                return Common.ErrorResult("未找到指定实体！");

            if (oldModel.IsSystem == true)
                return Common.ErrorResult("系统内置按钮不允许修改");

            if (IsExistCode(model.Code, model.Id))
            {
                return Common.ErrorResult("编码不能重复");
            }

            if (oldModel.ParentId != model.ParentId)
                if (GetDescendantIdsWithSelf(model.Id).Contains(model.ParentId))
                    return Common.ErrorResult("不能将按钮移动到自身或子孙按钮之下");

            if (model.ParentId == null)
            {
                model.Layer = 0;
            }
            else
            {
                var parent = _context.Sys_ModuleButtons.AsNoTracking().FirstOrDefault(x => x.Id == model.ParentId);
                if (parent == null)
                    return Common.ErrorResult("未找到指定的上级按钮");
                model.Layer = parent.Layer + 1;
            }
            
            _modelHandler.Update(model);
            _context.Update(model);
            _dbLogApp.LogUpdateInformation(model.Id, model,"更新按钮");
            _context.SaveChanges();
            return Common.SuccessResult();
        }

        /// <summary>
        /// 逻辑移除模块
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ModelResult Remove(string id)
        {
            var model = _context.Sys_ModuleButtons.FirstOrDefault(x => x.Id == id);
            if (model != null)
            {
                _modelHandler.Delete(model);
                _context.UpdateModel(model);
                _dbLogApp.LogRemoveInformation(model.Id, model,"逻辑删除按钮");
                _context.SaveChanges();
            }
            return Common.SuccessResult();
        }

        public ModelResult UpdateIsSystem(string id, bool issystem)
        {
            var model = _context.Sys_ModuleButtons.FirstOrDefault(x => x.Id == id);
            if (model == null)
                return Common.ErrorResult("未找到指定id的实体");

            model.IsSystem = issystem;
            _dbLogApp.LogUpdateInformation(id, model,"更新按钮【系统】标识"+issystem.ToString());
            _context.SaveChanges();

            return Common.SuccessResult();
        }

        public ModuleButtonModel Get(string id, bool containDeleted = false, bool include = false)
        {
            var data = _context.Sys_ModuleButtons.AsNoTracking();
            if (containDeleted == false)
                data = data.Where(x => x.DeleteMark != true);
            if (include == true)
                data = data.Include(m => m.CreateUser)
                .Include(m => m.DeleteUser)
                .Include(m => m.LastUpdateUser)
                .Include(m => m.Module)
                .Include(m => m.Parent);

            return data.FirstOrDefault(x => x.Id == id);
        }

        /// <summary>
        /// 是否存在指定编码
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool IsExistCode(string code)
        {
            return _context.Sys_ModuleButtons.Any(x => x.Code.ToUpper() == code.ToUpper());
        }

        /// <summary>
        /// 是否存在指定编码
        /// </summary>
        /// <param name="code"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool IsExistCode(string code, string id)
        {
            return _context.Sys_ModuleButtons.Any(x => x.Code.ToUpper() == code.ToUpper() && x.Id != id);
        }

        public bool IsModuleHasButtons(string moduleId)
        {
            return _context.Sys_ModuleButtons.Any(x => x.ModuleId == moduleId);
        }

        /// <summary>
        /// 获取包含自身的子孙按钮列表Id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IEnumerable<string> GetDescendantIdsWithSelf(string id, bool containDeleted = false)
        {
            var data = _context.Sys_ModuleButtons.AsNoTracking();
            if (containDeleted == false)
                data = data.Where(x => x.DeleteMark != true);

            var list = new List<string>();
            if (string.IsNullOrEmpty(id))
                return list;
            list.Add(id);
            var childrenIds = (from p in data.Where(x => x.ParentId == id) select p.Id).ToList();
            if (childrenIds.Count() <= 0)
                return list;
            else
            {
                foreach (var item in childrenIds)
                {
                    list.AddRange(GetDescendantIdsWithSelf(item));
                }
            }
            return list;
        }

        /// <summary>
        /// 获取TreeGrid根据指定的模块Id
        /// </summary>
        /// <param name="moduleId"></param>
        /// <returns></returns>
        public IEnumerable<ModuleButtonModel> GetTreeGridByModuleId(string moduleId, bool containDeleted = false)
        {
            var data = _context.Sys_ModuleButtons.AsNoTracking();
            if (containDeleted == false)
                data = data.Where(x => x.DeleteMark != true);
            var result = new List<ModuleButtonModel>();
            var buttons = data.Where(x => x.ModuleId == moduleId);
            result.AddRange(GetTreeGrid(buttons, null));
            return result;
        }

        private IEnumerable<ModuleButtonModel> GetTreeGrid(IEnumerable<ModuleButtonModel> data, string parentId)
        {
            var result = new List<ModuleButtonModel>();
            var children = data.Where(x => x.ParentId == parentId).OrderBy(x => x.SortCode);
            foreach (var item in children)
            {
                var model = item;
                result.Add(model);
                result.AddRange(GetTreeGrid(data, item.Id));
            }
            return result;
        }

        /// <summary>
        /// 获取选择列表
        /// </summary>
        /// <returns></returns>
        public IEnumerable<TreeCollapseModel> GetTreeCollapseItems(string moduleId)
        {
            var data = _context.IQueryable<ModuleButtonModel>().Where(x => x.DeleteMark != true && x.ModuleId == moduleId);
            var result = from item in data
                         select new TreeCollapseModel
                         {
                             Id = item.Id,
                             Text = item.Name,
                             ParentId = item.ParentId,
                             SortCode = item.SortCode,
                             Url = item.Url
                         };
            return result;

        }

        /// <summary>
        /// 获取按钮的关联策略列表
        /// </summary>
        /// <returns></returns>
        public List<StrategoryModel> GetRelatedStrategorysByButtonId(string buttonId)
        {
            var button = _context.Sys_ModuleButtons.AsNoTracking().FirstOrDefault(x => x.Id == buttonId);
            if (button == null)
                return null;

            var strategoryIds = from p in _context.Sys_StrategoryModuleButtons.Where(x => x.ModuleButtonId == buttonId)
                                select p.StrategoryId;

            var data = _context.Sys_Strategorys.AsNoTracking().Where(x => x.DeleteMark != true && (strategoryIds.Contains(x.Id) || x.IsSuper == true)).OrderBy(x => x.SortCode);
            return data.ToList();
        }
    }
}
